package com.xbank.app.service;

import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.app.api.AppClientFactory;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizMessage;
import com.bizmda.bizsip.common.BizMessageInterface;
import com.xbank.client.app.api.PersonalAppInterface;
import com.xbank.client.app.dto.CustomerAndAccountList;
import com.xbank.client.sink.account.api.AccountSinkInterface;
import com.xbank.client.sink.customer.api.CustomerSinkInterface;
import com.xbank.infrastructure.db.account.domain.Account;
import com.xbank.infrastructure.db.customer.domain.Customer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class PersonalAppService implements PersonalAppInterface {
    private AccountSinkInterface accountSinkInterface = AppClientFactory
            .getSinkClient(AccountSinkInterface.class,"account-sink");
    private CustomerSinkInterface customerSinkInterface = AppClientFactory
            .getSinkClient(CustomerSinkInterface.class,"customer-sink");
    private BizMessageInterface payment1SinkInterface = AppClientFactory
            .getSinkClient(BizMessageInterface.class,"payment1-sink");
    private BizMessageInterface payment2SinkInterface = AppClientFactory
            .getSinkClient(BizMessageInterface.class,"payment2-sink");
    private PersonalAppInterface personalAppDelayInterface = AppClientFactory
            .getDelayAppServiceClient(PersonalAppInterface.class,"/app/personal",
                    0,1000,2000,4000,8000,16000,32000);

    @Override
    public CustomerAndAccountList getCustomerAndAccountList(String customerId) {
        Customer customer = this.customerSinkInterface.getCustomer(customerId);
        List<Account> accountList = this.accountSinkInterface.getAccountListByCustomerId(customerId);
        CustomerAndAccountList customerAndAccountList = new CustomerAndAccountList();
        customerAndAccountList.setCustomer(customer);
        customerAndAccountList.setAccountList(accountList);
        return customerAndAccountList;
    }

    @Override
    public List<Account> getAccountListByCustomerId(String customerId) {
        return this.accountSinkInterface.getAccountListByCustomerId(customerId);
    }

    @Override
    public Customer getCustomer(String customerId) {
        return this.customerSinkInterface.getCustomer(customerId);
    }

    @Override
    public BizMessage<JSONObject> send2Payment1(Object message) throws BizException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("message",message);
        return this.payment1SinkInterface.call(jsonObject);
    }

    @Override
    public BizMessage send2Payment2(String tranMode, String tranCode, Object message) throws BizException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("tranCode",tranCode);
        jsonObject.set("tranMode",tranMode);
        jsonObject.set("message",message);
        return this.payment2SinkInterface.call(jsonObject);
    }

    @Override
    public Customer getCustomerAndSaf2Payment2(String tranMode,String customerId) throws BizException {
        Customer customer = this.customerSinkInterface.getCustomer(customerId);
        this.personalAppDelayInterface.send2Payment2(tranMode,"send-customer", customer);
        return customer;
    }

    @Override
    public Account payout(String accountId, long amount) {
        return this.accountSinkInterface.payout(accountId,amount);
    }

    @Override
    public void payoutForward(String tranMode,String accountId, long amount) throws BizException {
        log.info("account出金:{},{}",accountId,amount);
        this.accountSinkInterface.payout(accountId,amount);
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("tranCode","pay");
        jsonObject.set("tranMode",tranMode);
        jsonObject.set("accountId",accountId);
        jsonObject.set("tranAmount",amount);
        BizMessage<JSONObject> bizMessage = null;
        try {
            log.info("payment缴费...");
            bizMessage = this.payment2SinkInterface.call(jsonObject);
        } catch (BizException e) {
            if (e.isRetryDelayAppService()) {
                log.info("payment交易超时,开始payout补偿...");
                this.personalAppDelayInterface.payoutForwardCompensate(jsonObject);
                return;
            }
            else {
                throw e;
            }
        }
        log.info("payment缴费成功!");
        log.info("payout成功!");
    }

    @Override
    public void payoutForwardCompensate(JSONObject jsonObject)  throws BizException{
        jsonObject.set("tranCode","pay-query");
        BizMessage<JSONObject> bizMessage = null;
        try {
            log.info("payment查询缴费订单...");
            bizMessage = this.payment2SinkInterface.call(jsonObject);
        } catch (BizException e) {
            if (e.isRetryDelayAppService()) {
                log.info("payment交易超时...");
                throw e;
            }
            else {
                log.info("payment查询缴费订单返回错误（表示对方订单没执行）...");
                String accountId = (String)jsonObject.get("accountId");
                long amount = (Integer) jsonObject.get("tranAmount");
                log.info("account出金补偿:{},{}",accountId,amount);
                this.accountSinkInterface.payoutCompensation(accountId,amount);
                return;
            }
        }
        log.info("payment查询缴费订单成功（表示对方订单已执行）");
        log.info("payout成功!");
    }

    @Override
    public void payoutBackward(String tranMode, String accountId, long amount) throws BizException {
        log.info("account出金:{},{}",accountId,amount);
        this.accountSinkInterface.payout(accountId,amount);
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("tranCode","pay");
        jsonObject.set("tranMode",tranMode);
        jsonObject.set("accountId",accountId);
        jsonObject.set("tranAmount",amount);
        BizMessage<JSONObject> bizMessage = null;
        try {
            log.info("payment缴费...");
            bizMessage = this.payment2SinkInterface.call(jsonObject);
        } catch (BizException e) {
            if (e.isRetryDelayAppService()) {
                log.info("payment交易超时,开始payout冲正...");
                this.personalAppDelayInterface.payoutBackwardCompensate(jsonObject);
                return;
            }
            else {
                log.info("payment缴费交易返回错误");
                log.info("account出金补偿:{},{}",accountId,amount);
                this.accountSinkInterface.payoutCompensation(accountId,amount);
                log.info("payout交易补偿成功！");
                return;
            }
        }
        log.info("payment缴费成功");
        log.info("payout成功!");
    }

    @Override
    public void payoutBackwardCompensate(JSONObject jsonObject) throws BizException {
        jsonObject.set("tranCode","pay-reversal");
        BizMessage<JSONObject> bizMessage;
        try {
            log.info("payment缴费补偿...");
            bizMessage = this.payment2SinkInterface.call(jsonObject);
            log.info("payment缴费补偿成功");
        } catch (BizException e) {
            if (e.isRetryDelayAppService()) {
                log.info("payment缴费补偿交易超时...");
                throw e;
            }
            log.info("payment缴费补偿交易失败,需要人工干预调整!");
            return;
        }
        String accountId = (String)jsonObject.get("accountId");
        long amount = (Integer)jsonObject.get("tranAmount");
        log.info("account出金补偿:{},{}",accountId,amount);
        this.accountSinkInterface.payoutCompensation(accountId,amount);
        log.info("payout补偿成功！");
    }
}
